#pragma once
#include <iostream>
#include <unistd.h>
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"
class Channel
{
public:
    Channel(int wfd, int subpid)
        :_wfd(wfd)
        ,_subpid(subpid) 
    {
        std::cout << "" <<  std::endl;
    }

    void send(int code) 
    {
        int n = write(_wfd,&code,sizeof(code));
        (void)n;
    }

    void Close()
    {
        close(_wfd);
    }

    void Waitpid()
    {
        pid_t fd = waitpid(_subpid,nullptr,0);
        (void)fd;
    }

    ~Channel()
    {

    }
private:
    int _wfd;
    int _subpid;
};



class ChannelManger 
{
public:
    ChannelManger()
        :_next(0)
    {

    }
    void Insert(int wfd, int subpid) 
    {
        _Channel.emplace_back(wfd,subpid);
    }

    Channel& Select()
    {
        auto& c =_Channel[_next];
        _next++;
        _next %= _Channel.size();
        return c;
    }
    int Next()
    {
        return _next;
    }

    void ProcessPoolClose()
    {
        for(auto& c : _Channel)
        {
            c.Close();
            std::cout << "信道关闭" << std::endl;
        }
    }

    void ProcessPoolWait()
    {
        for(auto& c : _Channel)
        {
            c.Waitpid();
            std::cout << "子进程回收" << std::endl;
        }
    }
    ~ChannelManger()
    {

    }

private:
    std::vector<Channel> _Channel;
    int _next;
};

int num_fault = 5;

class ProcessPool
{
public:
    ProcessPool(int num)
        :_ProcessNum(num)
    {
        _tm.Register(task1);
        _tm.Register(task2);
        _tm.Register(task3);
    }
    void Work(int rfd) 
    {
        while(true) 
        {
            int code = 0;
            //int n = read(rfd,&node,sizeof(node));
            ssize_t n = read(rfd, &code, sizeof(code));
            if(n > 0) 
            {
                if(n != sizeof(code)) 
                {
                    continue;
                }
                _tm.Excute(code);   
            }
            else if (n == 0)
            {
                std::cout << "进程退出" << std::endl;
                break;
            }
            else
            {
                std::cout << "输入有误" << std::endl;
                break;
            }
        }
    }

    void Start() 
    {
        for(int i = 0; i < _ProcessNum; i++) 
        {
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if(n < 0) 
            {
                perror("create error");
            }
            //int fd = fork();
            pid_t subpid = fork();
            if(subpid < 0) 
            {
                perror("fork error");
            }
            else if (subpid == 0) 
            {
                //子进程
                close(pipefd[1]);
                Work(pipefd[0]);
                close(pipefd[0]);
                exit(0);
            }
            else
            {
                //父进程
                close(pipefd[0]);
                _cm.Insert(pipefd[1],subpid);
            }            
        }
    }

    void run()
    {
        //1.选择任务
        int TaskCode = _tm.Code();

        //2.选择信道
        auto& s = _cm.Select();
        std::cout << "选择了信道[" << _cm.Next() << "]" << std::endl;
        //3.发送指令
        s.send(TaskCode);
        std::cout << "执行任务[" << TaskCode << "]" << std::endl;
    }

    void stop()
    {
        _cm.ProcessPoolClose();
        _cm.ProcessPoolWait();
    }
    ~ProcessPool()
    {

    }
    private:
    ChannelManger _cm;
    int _ProcessNum;
    TaskManger _tm;
};